package com.example.demo.config

import com.fasterxml.jackson.databind.ObjectMapper
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.reflect.CodeSignature
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.annotation.Order
import org.springframework.stereotype.Component
import org.springframework.validation.BindingResult
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import java.util.*
import com.google.gson.Gson

import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.*

import javax.servlet.http.HttpServletRequest



@Aspect
@Component
class WebLogAspect {
    private val logger = LoggerFactory.getLogger(WebLogAspect::class.java)

    /** 以 controller 包下定义的所有请求为切入点  */
    @Pointcut("execution(public * com.example.demo.controller..*.*(..))")
    fun webLog() {
    }

    /**
     * 在切点之前织入
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLog()")
    @Throws(Throwable::class)
    fun doBefore(joinPoint: JoinPoint) {
        // 开始打印请求日志
        val attributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes?
        val request = attributes!!.request
        // 打印请求相关参数
        logger.info("========================================== Start ==========================================")
        // 打印请求 url
        logger.info("URL            : {}", request.requestURL.toString())
        // 打印 Http method
        logger.info("HTTP Method    : {}", request.method)
        // 打印调用 controller 的全路径以及执行方法
        logger.info("Class Method   : {}.{}", joinPoint.signature.declaringTypeName, joinPoint.signature.name)
        // 打印请求的 IP
        logger.info("IP             : {}", request.remoteAddr)
        // 打印请求入参
        logger.info("Request Args   : {}", Gson().toJson(joinPoint.args))
    }

    /**
     * 在切点之后织入
     * @throws Throwable
     */
    @After("webLog()")
    @Throws(Throwable::class)
    fun doAfter() {
        // 每个请求之间空一行
//        logger.info("")
    }

    /**
     * 环绕
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("webLog()")
    @Throws(Throwable::class)
    fun doAround(proceedingJoinPoint: ProceedingJoinPoint): Any? {
        val startTime = System.currentTimeMillis()
        val result = proceedingJoinPoint.proceed()
        // 打印出参
        logger.info("Response Args  : {}", Gson().toJson(result))
        // 执行耗时
        logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime)
        logger.info("=========================================== End ===========================================")
        return result
    }
}
